package cn.itcast.lock;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 虎哥
 */
public class SimpleRedisLock implements RedisLock {

    private String key;

    private StringRedisTemplate redisTemplate;

    private final String VALUE_PREFIX = UUID.randomUUID().toString() + "_";

    SimpleRedisLock(String key, StringRedisTemplate redisTemplate) {
        this.key = key;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean tryLock(long releaseTime, TimeUnit timeUnit) {
        // 获取进程和线程标识
        String value = VALUE_PREFIX + Thread.currentThread().getId();
        Boolean boo = redisTemplate.opsForValue().setIfAbsent(key, value, releaseTime, timeUnit);
        if(BooleanUtils.isFalse(boo)){
            // 获取锁失败，订阅消息队列
            // 阻塞，使用闭锁
            // 监听到锁释放消息后，再执行下面循环逻辑
        }
        // 获取锁，存入线程和进程标识
        while (!boo) {
            boo = redisTemplate.opsForValue().setIfAbsent(key, value, releaseTime, timeUnit);
        }
        return BooleanUtils.isTrue(boo);
    }

    @Override
    public void unlock() {
        // 获取进程和线程标识
        String value = VALUE_PREFIX + Thread.currentThread().getId();
        // 获取锁标识
        String threadId = redisTemplate.opsForValue().get(key);
        if(StringUtils.equalsIgnoreCase(value, threadId)) {
            // 释放锁
            redisTemplate.delete(key);
        }
    }
}
